<template>
  <h4>{{ title }}</h4>
  <canvas :id="key" class="c2d" width="1000" height="500"></canvas>
</template>

<script setup>
import { ref, onMounted } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { Water } from "three/examples/jsm/objects/Water.js";
import { Sky } from "three/examples/jsm/objects/Sky.js";

const key = ref("c2d" + Math.floor(Math.random() * 10000));
const props = defineProps({
  title: String,
});

onMounted(() => {
  const canvas = document.querySelector(`#${key.value}`);

  const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });

  // 1. 创建一个场景
  const scene = new THREE.Scene();
  // 2. 创建水波纹容器
  const waterGeometry = new THREE.PlaneGeometry(10000, 10000);
  // 3. 创建多面体
  const geometry = new THREE.DodecahedronGeometry(30);
  // 4. 水纹配置
  const waterOPtions = {
    textureWidth: 512,
    textureHeight: 512,
    waterNormals: new THREE.TextureLoader().load(
      "src/assets/img/waternormals.jpg",
      function (texture) {
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
      }
    ),
    sunDirection: new THREE.Vector3(),
    sunColor: 0xffffff,
    waterColor: 0x001e0f,
    distortionScale: 3.7,
    fog: scene.fog !== undefined,
  };
  // 水纹1
  const water = new Water(waterGeometry, waterOPtions);
  water.rotation.x = -Math.PI / 2;
  scene.add(water);
  // 水纹2
  const water2 = new Water(geometry, waterOPtions);
  scene.add(water2);

  // 5. 环境光（整个场景的光，添加后整个管道都能更明亮）
  const light = new THREE.AmbientLight(0xffffff, 1);
  scene.add(light);
  // 6. 创建太阳
  let sky = new Sky();
  let uniforms = sky.material.uniforms;
  uniforms["turbidity"].value = 10;
  uniforms["rayleigh"].value = 3;
  uniforms["mieCoefficient"].value = 0.005;
  uniforms["mieDirectionalG"].value = 0.7;
  let parameters = {
    distance: 400,
    inclination: 0.49, //倾向
    azimuth: 0.205, //方位角
  };
  const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(128, {
    format: THREE.RGBAFormat,
    generateMipmaps: true,
    minFilter: THREE.LinearMipmapLinearFilter,
  });

  const cubeCamera = new THREE.CubeCamera(0.01, 1000, cubeRenderTarget);

  let theta = Math.PI * (parameters.inclination - 0.5);
  let phi = 2 * Math.PI * (parameters.azimuth - 0.5);
  light.position.x = parameters.distance * Math.cos(phi);
  light.position.y = parameters.distance * Math.sin(phi) * Math.sin(theta);
  light.position.z = parameters.distance * Math.sin(phi) * Math.cos(theta);

  sky.material.uniforms["sunPosition"].value = light.position.copy(
    light.position
  );
  water.material.uniforms["sunDirection"].value = light.position
    .clone()
    .normalize();

  water2.material.uniforms["sunDirection"].value = light.position
    .clone()
    .normalize();
  cubeCamera.update(renderer, sky);
  scene.background = cubeRenderTarget.texture;

  // 7. 相机位置（拍照片，关键，Three的每一个帧需要拍下来才能显示）
  const camera = new THREE.PerspectiveCamera(30, 2, 0.1, 2000);
  // 超出视锥体的远裁截面的范围会被剪掉
  camera.position.set(200, 10, 100);
  // 定义相机的视线
  camera.lookAt(0, 0, 0);
  // 控制相机
  const controls = new OrbitControls(camera, canvas);
  controls.update();

  // 8. 渲染方法
  renderer.setSize(1000, 500);
  // 用相机(camera)渲染一个场景(scene)。类比相机的拍照动作
  renderer.render(scene, camera);

  // 9. 循环
  function render() {
    // 周期性渲染，更新 canvas 画布的内容
    renderer.render(scene, camera);
    requestAnimationFrame(render);
    water.material.uniforms["time"].value += 1.0 / 60.0;
    water2.material.uniforms["time"].value += 1.0 / 60.0;
  }
  render();

  // 10. 这一步是优化，在窗口改变时，canvas 位置也跟着改变
  // window.onresize = function () {
  //   renderer.setSize(window.innerWidth, window.innerHeight);
  //   // 相机宽高比
  //   camera.aspect = window.innerWidth / window.innerHeight;
  //   // 更新摄像机投影矩阵
  //   camera.updateProjectionMatrix();
  // };
});
</script>

<style scoped>
.read-the-docs {
  color: #888;
}
</style>
